﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CC.UI
{
    [Browsable(true), Description("没有行标题的滑动条")]
    public partial class CcSliderNoRowTitle : UserControl
    {
        public delegate void ValueChangeHandler(object sender,EventArgs e);
        internal ClearSlidersStatus ClearStatus { get; set; }
        private float mMin;
        private float mMax;
        private float mStep;
        private float mSmallChange;
        private float mLargeChange;
        private float mTickFrequency;
        private float mValue;
        private bool mLoaded = false;//是否装载完毕

        [Category("操作"), Browsable(true), Description("当前值")]
        public event ValueChangeHandler ValueChanged;
        [Category("数据"), Browsable(true), Description("当前值")]
        public float Value
        {
            get {
                return mValue;
            }
            set
            {
                if (!float.IsNaN(value) && !float.IsInfinity(value) && value >= mMin && value <= mMax)//处理数据异常
                {
                    mValue = value;
                    txtValue.Text = "" + value;
                    InitialTrackBar();
                }
                    
            }
        }
        [Category("数据"), Browsable(true), Description("最大值")]
        public float Maximum
        {
            get
            {
                return mMax;
            }
            set
            {
                if (!float.IsNaN(value) && !float.IsInfinity(value) && value > mMin)//处理数据异常
                {
                    mMax = value;
                    txtMax.Text = "" + value;
                    InitialTrackBar();
                }
            }
        }
        [Category("数据"), Browsable(true), Description("最小值")]
        public float Minimum
        {
            get
            {
                return mMin;
            }
            set
            {
                if (!float.IsNaN(value) && !float.IsInfinity(value) && value < mMax)//处理数据异常
                {
                    mMin = value;
                    txtMin.Text = "" + value;
                    InitialTrackBar();
                }
            }
        }
        [Category("数据"), Browsable(true), Description("调节步长")]
        public float Step
        {
            get
            {
                return mStep;
            }
            set
            {
                if (!float.IsNaN(value) && !float.IsInfinity(value) && value != 0 && value < mMax - mMin) //处理数据异常
                {
                    mStep = value;
                    txtStep.Text = "" + value;
                    InitialTrackBar();
                }
                
                
            }
        }
        [Category("行为"), Browsable(true), Description("标尺频度")]
        /// <summary>
        /// 刻度频度
        /// </summary>
        public float TickFrequency
        {
            get { return mTickFrequency; }
            set
            {
                if (!float.IsNaN(value) && !float.IsInfinity(value) && value < mMax - mMin)//处理数据异常
                {
                    mTickFrequency = value;
                    trackBar.TickFrequency = (int)(value / mStep);
                }
                  
            }
        }
        [Category("行为"), Browsable(true), Description("鼠标在滑动条两侧点击时的数值步长")]
        /// <summary>
        /// 每次鼠标在滑动条两侧点击时的数值步长
        /// </summary>
        public float LargeChange
        {
            get { return mLargeChange; }
            set
            {
                if (!float.IsNaN(value) && !float.IsInfinity(value) && value > mSmallChange)//处理数据异常
                {
                    mLargeChange = value;
                    trackBar.LargeChange = (int)(value / mStep);
                }
                    
            }
        }
        [Category("行为"), Browsable(true), Description("使用键盘光标键时的数值步长")]
        /// <summary>
        /// 每次使用键盘光标键时的数值步长
        /// </summary>
        public float SmallChange
        {
            get { return mSmallChange; }
            set
            {
                if (!float.IsNaN(value) && !float.IsInfinity(value) || value < mLargeChange)//处理数据异常
                {
                    mSmallChange = value;
                    trackBar.SmallChange = (int)(mSmallChange / mStep);
                }
                    
            }
        }
        /// <summary>
        /// 是否刚被调用过
        /// </summary>
        public bool IsLastInvoked { get; internal set; }

        public bool IsValueChanged { get; private set; }
        public CcSliderNoRowTitle()
        {
            InitializeComponent();
            
            Maximum = 3;
            Minimum = 0;
            Step = 0.1f;
            trackBar.Minimum = 0;
            TickFrequency = 0.5f;
            LargeChange = 0.2f;
            SmallChange = 0.1f;
            
        }
        /// <summary>
        /// 带参数创建滑动条
        /// </summary>
        /// <param name="name">滑动条名称</param>
        /// <param name="max">最大值，必须大于最小值</param>
        /// <param name="min">最小值，必须小于最大值</param>
        /// <param name="step">步长，0时则自动10分之</param>
        public CcSliderNoRowTitle(string name,double value, double max=5,double min=0,double step=0)
        {
            InitializeComponent();
            if (max < min)//确保min<max
            {
                max = min + (min = max) * 0;//max <==>min
            }
            else if (max == min) min = max - 10;
            if (step == 0) step = (max - min) / 50;//防止step出现0
            Name = name;
            Maximum = (float)max;
            Minimum = (float)min;
            Step = (float)step;
            if (value > max) Value = (float)max;
            else if (value < min) Value = (float)min;
            else Value = (float)value;
            TickFrequency = (float)(max - min) / 5;
            LargeChange = (float)step * 3;
            SmallChange = (float)step;
        }
        private void CcSliderNoRowTitle_Load(object sender, EventArgs e)
        {
            lbName.Text = Name;
            txtMax.Text = "" + mMax;
            txtMin.Text = "" + mMin;
            txtStep.Text = "" + mSmallChange;
            txtValue.Text = "" + mValue;
            mLoaded = true;
        }
        private void InitialTrackBar()
        {
            if (mMin < mMax && mStep < (mMax - mMin) && mStep > 0 && mValue<=mMax && mValue >= mMin) 
            {
                trackBar.Maximum = (int)((mMax - mMin) / mStep);
                trackBar.Minimum = 0;
                trackBar.Value = (int)((mValue - mMin) / mStep); ;
            }
        }
        private void trackBar_Scroll(object sender, EventArgs e)
        {
            Value = trackBar.Value * Step + Minimum;
            txtValue.Text = "" + Value;
        }

        private void txtValue_Validated(object sender, EventArgs e)
        {
            if(float.TryParse(txtValue.Text,out float value))
            {
                Value = value;
            }
            else
            {
                txtValue.Text = "" + Value;
            }
        }

        private void txtValue_KeyPress(object sender, KeyPressEventArgs e)
        {
            if(e.KeyChar=='\r' )
            {
                txtValue_Validated(sender, e);
            }
        }

        private void txtMax_Validated(object sender, EventArgs e)
        {
            if (float.TryParse(txtMax.Text, out float value))
            {
                Maximum = value;
            }
            else
            {
                txtMax.Text = "" + Maximum;
            }
        }

        private void txtMax_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == '\r')
            {
                txtMax_Validated(sender, e);
            }
        }

        private void txtMin_Validated(object sender, EventArgs e)
        {
            if (float.TryParse(txtMin.Text, out float value))
            {
                Minimum = value;
            }
            else
            {
                txtMin.Text = "" + Minimum;
            }
        }

        private void txtMin_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == '\r')
            {
                txtMin_Validated(sender, e);
            }
        }

        private void txtStep_Validated(object sender, EventArgs e)
        {
            if (float.TryParse(txtStep.Text, out float value))
            {
                Step = value;
            }
            else
            {
                txtStep.Text = "" + Step;
            }
        }

        private void txtStep_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == '\r')
            {
                txtStep_Validated(sender, e);
            }
        }
        //
        private void CcSlider_Resize(object sender, EventArgs e)
        {
            if(Height>this.MinimumSize.Height)
            {
                trackBar.Height = Height - trackBar.Location.Y - txtMin.Height - txtStep.Height - lbName.Height - 4 * 3;
                int locY = trackBar.Location.Y + trackBar.Height + 3;
                txtMin.Location = new Point(txtMin.Location.X, locY);
                locY = txtMin.Location.Y + txtMin.Height + 3;
                txtStep.Location = new Point(txtMin.Location.X, locY);
                locY = txtStep.Location.Y + txtStep.Height + 3;
                lbName.Location = new Point(txtMin.Location.X, locY);
            }
            
        }
        internal Point TextMinLocation { get { return txtMin.Location; } }
        internal Point TextStepLocation { get { return txtStep.Location; } }

        private void trackBar_ValueChanged(object sender, EventArgs e)
        {
            if (ClearStatus != null) Invoke(ClearStatus);
            IsLastInvoked = true;
            IsValueChanged = true;
           if(mLoaded) Invoke(ValueChanged,sender,e);
        }
    }
}
